// Package util
// @Title util[简述该包的主要作用]
// @Description
// @Author  cnHuaShao
// @since v0.0.1
// @Version v1.0.0
// @Date 2024/4/21 21:50
// @Update 2024/4/21 21:50
package util

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"time"
	"unsafe"
)

func GetURL(r *http.Request) (Url string) {
	scheme := "http://"
	if r.TLS != nil {
		scheme = "https://"
	}
	return strings.Join([]string{scheme, r.Host, "/"}, "")
}

// HttpGet 发送GET请求
// @Description: 模拟浏览器发送Http的Get请求到指定链接并接收返回值
// @param url 请求url
// @return response 响应对象
// @return err 错误信息
func HttpGet(url string) (response string, err error) {
	client := http.Client{Timeout: 5 * time.Second}
	resp, err := client.Get(url)
	defer resp.Body.Close()
	if err != nil {
		return "", err
	}
	var buffer [512]byte
	result := bytes.NewBuffer(nil)
	for {
		n, err := resp.Body.Read(buffer[0:])
		result.Write(buffer[0:n])
		if err != nil && err == io.EOF {
			break
		} else if err != nil {
			panic(err)
		}
	}
	return result.String(), nil
}

// HttpFormDataPost 发送POST请求（form-data）
// @Description: 模拟浏览器发送Http的Post请求并携带form-data数据到指定链接并接收返回值
// @param url 请求url
// @param postData 请求数据
// @return string 响应数据
// @return error 错误信息
func HttpFormDataPost(url string, postData *map[string]string) (string, error) {
	body := new(bytes.Buffer)
	w := multipart.NewWriter(body)
	for k, v := range *postData {
		if e := w.WriteField(k, v); e != nil {
			return "", e
		}
	}
	if e1 := w.Close(); e1 != nil {
		return "", e1
	}
	req, e3 := http.NewRequest("POST", url, body)
	if e3 != nil {
		return "", e3
	}
	req.Header.Set("Content-Type", w.FormDataContentType())
	// 设置特定的请求头
	req.Header.Set("UID", "TC031") // 替换为你的认证令牌
	resp, e4 := http.DefaultClient.Do(req)
	if e4 != nil {
		return "", e4
	}
	data, e5 := ioutil.ReadAll(resp.Body)
	if e5 != nil {
		return "", e5
	}
	defer resp.Body.Close()
	result := string(data)
	return result, nil
}

// postReq
// @Description:
// @param name
// @param age
func postReq(name string, age int) {
	client := &http.Client{}

	req, err := http.NewRequest("POST", "http://localhost:5000/post",
		strings.NewReader(fmt.Sprintf("name=%s&age=%d", name, age)))
	if err != nil {
		panic(err)
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	resp, err := client.Do(req)

	defer resp.Body.Close()

}

// HttpJSONDataPost
// @Description: 发送post请求，json格式
// @param b
// @param url
// @return string
// @return error
func HttpJSONDataPost(b []byte, url string) (string, error) {
	reader := bytes.NewReader(b)
	request, err := http.NewRequest("POST", url, reader)
	if err != nil {
		fmt.Println(err.Error())
		return "", err
	}
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	client := http.Client{}
	resp, err := client.Do(request)
	if err != nil {
		fmt.Println(err.Error())
		return "", err
	}
	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err.Error())
		return "", err
	}
	// byte数组直接转成string，优化内存
	str := (*string)(unsafe.Pointer(&respBytes))
	return *str, nil
}

func FilteParam(param string) string {
	log.Println(url.QueryEscape(param))
	param = strings.TrimSpace(url.QueryEscape(param))
	return param
}

// AddSlashes 函数返回在预定义字符之前添加反斜杠的字符串。
// 预定义字符是：
// 单引号（'）
// 双引号（"）
// 反斜杠（\）
func AddSlashes(str string) string {
	var tmpRune []rune
	strRune := []rune(str)
	for _, ch := range strRune {
		switch ch {
		case []rune{'\\'}[0], []rune{'"'}[0], []rune{'\''}[0]:
			tmpRune = append(tmpRune, []rune{'\\'}[0])
			tmpRune = append(tmpRune, ch)
		default:
			tmpRune = append(tmpRune, ch)
		}
	}
	return string(tmpRune)
}

// StripSlashes 函数删除由 addslashes() 函数添加的反斜杠。
func StripSlashes(str string) string {
	var dstRune []rune
	strRune := []rune(str)
	strLenth := len(strRune)
	for i := 0; i < strLenth; i++ {
		if strRune[i] == []rune{'\\'}[0] {
			i++
		}
		dstRune = append(dstRune, strRune[i])
	}
	return string(dstRune)
}

func SafeFilter(str string) string {
	// 给单引号（'）、双引号（"）、反斜线（\）与 NUL（NULL 字符）加上反斜线转义
	str = AddSlashes(str)
	// 删除非打印字符，粗暴式过滤xss可疑字符串
	str = regexp.MustCompile(str).String()
	return str
}
